/***************************************************************************
 *	@file 		fetion_util.h
 *	@Author 	baoyu0125@gmail.com
 *	@create		2011-7
 *	@version 	1.0.0
 *	@brief		common header file of whole program, contain all widely used
 *				header file and definition of utility related class: display
 *				string and xml parser.
 *	@modify		none
 ***************************************************************************/

#ifndef FETION_UTIL_H
#define FETION_UTIL_H

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include <string.h>
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <list>
#include <map>
#include <stdarg.h>
#include <exception>
#include <stdexcept>
#include <algorithm>
#include <termios.h>
#include <fcntl.h>
#include <time.h>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <openssl/crypto.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <libxml++/libxml++.h>
#include <termios.h>
#include <boost/interprocess/sync/lock_options.hpp>
//#include <conio.h>

// for debugging
//#define DONT_LOGIN

#define FETION_LOG
#ifdef FETION_LOG
	#define WRITE_LOG(...) fetionlog->print_log(__VA_ARGS__)
#else
	#define WRITE_LOG
#endif

#define NAVIGATION_URI "nav.fetion.com.cn"
#define INPUTBUFSIZE 4096
#define PLACEHOLDER "\t\t\t\t\t\t\t\t\t\t\t\t"
#define MOBILENO_LEN 11
#define FETIONNO_LEN 9

extern char inputbuf[INPUTBUFSIZE];

typedef std::map<int, std::string> stateMap;
typedef std::map<int, std::string>::value_type stateMapValue;

typedef enum {LOG_TRACE = 0, LOG_WARNING, LOG_FATAL, LOG_DEBUG} logType;

typedef enum {
	FUNC_SUCC = 0,		// function succeed
	FUNC_FAIL = 1		// function failed
} func_return;

typedef enum {
	BLACK=30, 
	RED=31, 
	GREEN=32,  
	BROWN=33,  
	BLUE=34,  
	PURPLE=35, 
	CYAN=36,  
	WHITE=37,  

	BACK_BLACK=40,  
	BACK_RED=41,
	BACK_GREEN=42,
	BACK_BROWN=43,
	BACK_BLUE=44,
	BACK_PURPLE=45,
	BACK_CYAN=46,
	BACK_WHITE=47,

	MAX_COLOR_LEN=10240
} string_color;

class programString
{
public:
	friend FILE* operator <<(FILE *fd, programString &pstr);
	
	programString(int str_len);
	programString(const programString &pstr);
	
	virtual ~programString() 
	{
		des_string();
	}
	virtual void set_font() = 0;
	virtual void print_input_buf(FILE *fp) = 0;
	programString &operator= (programString &rhs);
	programString &operator() (const char *rhs,...);
	const char *get_str() { return str; }
	
protected:
	int color(int colorfront=WHITE, int colorback=BACK_BLACK, bool bold=true,
			bool glint=false, bool underline=false);
	void position(const int row, const int col);
	char *str;
	unsigned int len;
private:
	void des_string()
	{
		if(str) { 
			delete []str;
			str = NULL;
		} 
	}
};

class sysinfoString : public programString
{
public:
	sysinfoString(const char *src_str, ...);
	void print_input_buf(FILE *fp)
	{}
	void set_font() 
	{ 
		color(GREEN, WHITE, true, false, false); 
	}	
};

class messageString : public programString
{
public:
	messageString(const char *src_str, ...);
	void print_input_buf(FILE *fp)
	{
		fprintf(fp, "%s", inputbuf);
	}
	void set_font() 
	{ 
		color(BLUE, WHITE, true, false, false);
	}	
};

class errorString : public programString
{
public:
	errorString(const char *src_str, ...);
	void print_input_buf(FILE *fp)
	{
//		fprintf(fp, "%s", inputbuf);
	}
	void set_font() 
	{ 
		color(RED, WHITE, true, false, false); 
	}	
};

class listenString : public programString
{
public:
	listenString(const char *src_str, ...);
	void print_input_buf(FILE *fp)
	{
		fprintf(fp, "%s", inputbuf);
	}
	void set_font() 
	{ 
		color(BROWN, WHITE, true, false, false);
		position(1000, 1);
	}	
};

class fetionLog
{
public:
	fetionLog(const char *logpath = "../log/clfetion.log");
	fetionLog(const fetionLog &flog) : filestream(flog.filestream), use(flog.use) { ++*use; }

	~fetionLog() 
	{
		if(0 == --*use) {
			if(NULL != filestream) fclose(filestream);
			delete use;
		}
	}
	int print_log(logType logtype, const char *log,...) const;
	
private:
	FILE *filestream;
	size_t *use;
};

class xmlParser : public xmlpp::DomParser
{
public:
	xmlpp::Node *get_specify_node(xmlpp::Node *pNode, std::string name) const;
	xmlpp::Node *get_specify_node_from_root(std::string name) const;
	std::string xml_get_text_content(const xmlpp::Node *pnode) const;
};

class Command
{
public:
	enum {
		CMD_QUIT_PROGRAM = 1,
		CMD_LISTS_COMMAND_LIST = 2, 
		CMD_LISTS_CONTACTS_LIST = 3,
		CMD_SEND_TO_RECENT_CONTACT = 4,
		CMD_SEND_TO_INDICATED_CONTACT = 5,
		CMD_CLEAR_SCREEN = 6,
		CMD_GET_CONTACT_INFORMATION = 7,
		CMD_SEND_DIRECT_SMS = 8,
		CMD_SEND_TO_PHONE = 9,
		CMD_ACCEPT_ADD_BUDDY_REQUEST = 10,
		CMD_REFUSE_ADD_BUDDY_REQUEST = 11
	};
	Command(const std::string &cmd) : cmdstr(cmd) {}
	Command() {}
	static void setCmdMap();
	void parse_command();
public:
	std::string cmdstr;
	int choiceIndex;
	int paraIndex;
	std::string paraString;
	bool addBuddyResult;
	static std::map<std::string, int> cmdMap;
	bool quit;
};

extern fetionLog *fetionlog;

FILE* operator<<(FILE *fd, programString &pstr);

struct tm* get_currenttime();

std::string hextostr(const unsigned char *in, int len);

unsigned char* strtohex(const char *in, int *len);

std::string get_sid_from_sipuri(std::string &sipuri);

void xml_convert(std::string &in);

struct tm convert_date(const std::string &date);

void set_input_attribute();

void reset_input_attribute();

#endif
